require 'pathname'
require 'uri'
require 'cgi'
require 'fastimage'


rule "IMAGE001", "Images should be preceded by an empty line" do
  tags :images, :spacing
  docs "https://github.com/YOUR_USERNAME/markdownlint/blob/master/docs/RULES.md#md999"
  aliases "image-empty-line-before"
  params :ignore_after_headings => false
  params :height_from => 30
  params :height_to => nil

  check do |doc, filename|
    height_from = @params[:height_from]
    height_to = @params[:height_to]

    height_range = "> #{height_from}"
    if height_to
      height_range = "within (#{height_from}, #{height_to})"
    end

    errors = []
    in_code_block = false
    image_link_regex = /!\[.*?\]\(.*?\)/
    image_path_regex = /(?<=\().*?(?=\))/

    doc.lines.each_with_index do |line, line_number|
      # 跳过代码块
      if line.match?(/^```/)
        in_code_block = !in_code_block
        next
      end
      next if in_code_block

      # TODO 跳过引用，设置为可配置
      if line.strip().match?(/^>/)
        next
      end

      # TODO 跳过表格，设置为可配置
      if line.strip().match?(/^\|/)
        next
      end



      current_line_number = line_number + 1  # line_number starts with 0

      # 检测图片语法
      img_pos = line.strip().index(image_link_regex)
      next unless img_pos
      if img_pos == 0
          previous_line = doc.lines[line_number - 1]
          # 前一行不是空行
          # TODO 设置为可配置项。因为有的Markdown渲染器会自动增加一行空白。
          unless previous_line.strip.empty?
            # errors << current_line_number
          end
      else
        # 图片在一行字符串内
        # TODO 某些内容包含图标，确实需要放在同一行。检查图片大小，高度在一定范围内再报错。
        line.strip().scan(image_link_regex).flatten.each do |img_link|
          img_path_attr = image_path_regex.match(img_link)[0]
          img_uri = URI(CGI.escape(img_path_attr))

          unless img_uri.scheme
            # 图片路径不是http/https等URI，尝试用本地路径解析
            pn = Pathname.new(img_path_attr)
            unless pn.absolute?
              # 通过文档路径和图片相对路径构造绝度路径
              dir = File.dirname(filename)
              img_uri = dir + "/" + img_path_attr
            else
              img_uri = img_path_attr
            end
          else
            img_uri = img_uri.to_s()
          end

          _, height = FastImage.size(img_uri)

          # puts "finally, image uri is " + img_uri + " #{height}"

          unless height
            # height is nil, no size parsed
            puts "[DEBUG] Line #{current_line_number}: image #{img_uri} without size"
            errors << current_line_number
            next
          end

          # img_height_match应该为false，代表不在指定的无效高度范围内
          # TODO 从使用者角度看，这个高度范围的概念有点绕，应该重新设计
          img_height_match = height > height_from
          if height_to
            img_height_match &&= height < height_to
          end

          if img_height_match
            puts "[DEBUG] Line #{current_line_number}: image #{img_uri} height #{height}, should not be #{height_range}"
            errors << current_line_number
          end
        end
      end
    end

    errors
  end
end
